// 玩家应用服务

import { Player, Achievement } from '../domain/models/Player';
import { PlayerService, IPlayerService } from '../domain/services/PlayerService';
import { IPlayerRepository, PlayerRepositoryFactory } from '../data/repositories/PlayerRepository';
import { AppError, ErrorType } from '../infrastructure/error/AppError';
import { DateUtils } from '../infrastructure/utils/DateUtils';

/**
 * 玩家应用服务接口
 * 提供给UI层调用的服务接口
 */
export interface IPlayerAppService {
  /**
   * 创建新玩家
   * @param name 玩家名称
   * @param avatar 头像URL
   * @returns 新创建的玩家信息
   */
  createPlayer(name: string, avatar?: string): Promise<Player>;

  /**
   * 获取玩家详情
   * @param playerId 玩家ID
   * @returns 玩家详情
   */
  getPlayerDetails(playerId: number): Promise<Player>;

  /**
   * 获取所有玩家
   * @returns 玩家列表
   */
  getAllPlayers(): Promise<Player[]>;

  /**
   * 更新玩家基本信息
   * @param playerId 玩家ID
   * @param name 玩家名称
   * @param avatar 头像URL
   * @returns 更新后的玩家信息
   */
  updatePlayerProfile(playerId: number, name: string, avatar?: string): Promise<Player>;

  /**
   * 玩家完成案件
   * @param playerId 玩家ID
   * @param caseId 案件ID
   * @param success 是否成功解决
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 更新后的玩家信息
   */
  completeCase(playerId: number, caseId: number, success: boolean, startTime: string, endTime?: string): Promise<Player>;

  /**
   * 获取玩家排行榜
   * @param limit 限制返回数量
   * @returns 排行榜数据
   */
  getPlayerRanking(limit?: number): Promise<any[]>;

  /**
   * 获取玩家成就列表
   * @param playerId 玩家ID
   * @returns 成就列表
   */
  getPlayerAchievements(playerId: number): Promise<Achievement[]>;
}

/**
 * 玩家应用服务实现
 */
export class PlayerAppService implements IPlayerAppService {
  private playerService: IPlayerService;
  private playerRepository: IPlayerRepository;

  /**
   * 构造函数
   */
  constructor() {
    // 依赖注入
    this.playerRepository = PlayerRepositoryFactory.createRepository();
    this.playerService = new PlayerService();
  }

  /**
   * 获取所有玩家
   */
  async getAllPlayers(): Promise<Player[]> {
    try {
      // 调用领域服务获取所有玩家
      return await this.playerService.getAllPlayers();
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw AppError.systemError('获取玩家列表失败', 'GET_ALL_PLAYERS_FAILED', error as Error);
    }
  }

  /**
   * 创建新玩家
   */
  async createPlayer(name: string, avatar?: string): Promise<Player> {
    try {
      // 参数验证
      if (!name || name.trim().length === 0) {
        throw AppError.validationError('玩家名称不能为空', 'INVALID_PLAYER_NAME');
      }

      if (name.length > 20) {
        throw AppError.validationError('玩家名称不能超过20个字符', 'PLAYER_NAME_TOO_LONG');
      }

      // 调用领域服务创建玩家
      const newPlayer = await this.playerService.createPlayer(name, avatar);
      
      // 保存到数据仓库
      return await this.playerRepository.save(newPlayer);
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw AppError.systemError('创建玩家失败', 'PLAYER_CREATION_FAILED', error as Error);
    }
  }

  /**
   * 获取玩家详情
   */
  async getPlayerDetails(playerId: number): Promise<Player> {
    try {
      // 参数验证
      if (!playerId || playerId <= 0) {
        throw AppError.validationError('无效的玩家ID', 'INVALID_PLAYER_ID');
      }

      // 从数据仓库获取玩家
      const player = await this.playerRepository.findById(playerId);
      
      if (!player) {
        throw AppError.notFoundError(`玩家ID ${playerId} 不存在`, 'PLAYER_NOT_FOUND');
      }

      // 更新最后登录时间
      player.lastLoginDate = DateUtils.getCurrentISOString();
      await this.playerRepository.update(player);
      
      return player;
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw AppError.systemError('获取玩家详情失败', 'GET_PLAYER_DETAILS_FAILED', error as Error);
    }
  }

  /**
   * 更新玩家基本信息
   */
  async updatePlayerProfile(playerId: number, name: string, avatar?: string): Promise<Player> {
    try {
      // 参数验证
      if (!playerId || playerId <= 0) {
        throw AppError.validationError('无效的玩家ID', 'INVALID_PLAYER_ID');
      }

      if (!name || name.trim().length === 0) {
        throw AppError.validationError('玩家名称不能为空', 'INVALID_PLAYER_NAME');
      }

      if (name.length > 20) {
        throw AppError.validationError('玩家名称不能超过20个字符', 'PLAYER_NAME_TOO_LONG');
      }

      // 获取玩家
      const player = await this.playerRepository.findById(playerId);
      if (!player) {
        throw AppError.notFoundError(`玩家ID ${playerId} 不存在`, 'PLAYER_NOT_FOUND');
      }

      // 更新玩家信息
      player.name = name;
      if (avatar !== undefined) {
        player.avatar = avatar;
      }
      player.lastLoginDate = DateUtils.getCurrentISOString();

      // 保存更新
      return await this.playerRepository.update(player);
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw AppError.systemError('更新玩家信息失败', 'UPDATE_PLAYER_PROFILE_FAILED', error as Error);
    }
  }

  /**
   * 玩家完成案件
   */
  async completeCase(playerId: number, caseId: number, success: boolean, startTime: string, endTime?: string): Promise<Player> {
    try {
      // 参数验证
      if (!playerId || playerId <= 0) {
        throw AppError.validationError('无效的玩家ID', 'INVALID_PLAYER_ID');
      }

      if (!caseId || caseId <= 0) {
        throw AppError.validationError('无效的案件ID', 'INVALID_CASE_ID');
      }

      // 获取玩家
      const player = await this.playerRepository.findById(playerId);
      if (!player) {
        throw AppError.notFoundError(`玩家ID ${playerId} 不存在`, 'PLAYER_NOT_FOUND');
      }

      // 检查玩家是否正在处理这个案件
      if (player.currentCaseId !== undefined && player.currentCaseId !== caseId) {
        throw AppError.businessError('玩家当前正在处理其他案件', 'PLAYER_BUSY_WITH_OTHER_CASE');
      }

      // 计算案件用时（分钟）
      const playTime = DateUtils.calculateMinutesDiff(startTime, endTime);

      // 更新玩家统计信息
      await this.playerService.updateCaseStats(playerId, success ? 'success' : 'failure', playTime);

      // 如果成功破案，添加经验值
      if (success) {
        // 根据用时给予不同的经验奖励（越快破案奖励越高）
        let expReward = 100;
        if (playTime < 30) {
          expReward = 200; // 30分钟内破案额外奖励
        } else if (playTime < 60) {
          expReward = 150; // 60分钟内破案额外奖励
        }
        
        await this.playerService.addExperience(playerId, expReward);
      } else {
        // 失败也给予少量经验作为鼓励
        await this.playerService.addExperience(playerId, 20);
      }

      // 标记案件完成
      player.completeCase();

      // 保存更新后的玩家信息
      return await this.playerRepository.update(player);
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw AppError.systemError('处理案件完成失败', 'COMPLETE_CASE_FAILED', error as Error);
    }
  }

  /**
   * 获取玩家排行榜
   */
  async getPlayerRanking(limit: number = 10): Promise<any[]> {
    try {
      // 参数验证
      if (limit <= 0 || limit > 100) {
        throw AppError.validationError('排行榜数量限制必须在1-100之间', 'INVALID_RANKING_LIMIT');
      }

      // 获取排行榜
      return await this.playerService.getPlayerRanking(limit);
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw AppError.systemError('获取玩家排行榜失败', 'GET_RANKING_FAILED', error as Error);
    }
  }

  /**
   * 获取玩家成就列表
   */
  async getPlayerAchievements(playerId: number): Promise<Achievement[]> {
    try {
      // 参数验证
      if (!playerId || playerId <= 0) {
        throw AppError.validationError('无效的玩家ID', 'INVALID_PLAYER_ID');
      }

      // 获取玩家
      const player = await this.playerRepository.findById(playerId);
      if (!player) {
        throw AppError.notFoundError(`玩家ID ${playerId} 不存在`, 'PLAYER_NOT_FOUND');
      }

      // 返回成就列表（按解锁时间排序）
      return [...player.achievements].sort((a, b) => 
        new Date(b.unlockedAt).getTime() - new Date(a.unlockedAt).getTime()
      );
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      throw AppError.systemError('获取玩家成就失败', 'GET_ACHIEVEMENTS_FAILED', error as Error);
    }
  }
}

/**
 * 玩家应用服务工厂
 */
export class PlayerAppServiceFactory {
  /**
   * 创建玩家应用服务实例
   * @returns 玩家应用服务实例
   */
  static createService(): IPlayerAppService {
    return new PlayerAppService();
  }
}